package com.loe.ktui

import android.content.Context
import android.content.res.TypedArray
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import androidx.core.content.res.getBooleanOrThrow
import androidx.core.content.res.getDimensionOrThrow
import androidx.core.content.res.getIntOrThrow
import androidx.core.view.children
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentPagerAdapter
import androidx.viewpager.widget.PagerAdapter
import androidx.viewpager.widget.ViewPager
import com.loe.ktui.util.KtCornerProvider
import com.loe.ktui.util.KtFragItem

open class UiViewPager(id: String? = null) : UiGroup(id)
{
    var pageLimit: Int? = null

    var canMove: Boolean = true

    var fragmentManager: FragmentManager? = null
    var fragItems: List<KtFragItem>? = null
    var fragments: List<Fragment>? = null

    open fun initUI(context: Context, view: KtViewPager)
    {
        super.initUI(context, view)

        isAlphaClick?.let { view.isAlphaClick = it }

        view.canMove = canMove

        pageLimit?.let { view.offscreenPageLimit = if (it >= childs.size) childs.size - 1 else it }

        // frag模式
        if (fragItems != null)
        {
            view.setFragItems(fragItems!!, fragmentManager)
        } else if (fragments != null)
        {
            view.setFragments(fragments!!, fragmentManager)
        }
        // view模式
        else
        {
            val viewList = ArrayList<View>()
            if (childs.isNotEmpty())
            {
                childs.forEach()
                {
                    viewList.add(it.createView(context))
                }
            }
            view.setViewList(viewList)
        }
    }

    /** 创建view */
    override fun createView(context: Context, parent: ViewGroup?): KtViewPager
    {
        return KtViewPager(context).also()
        {
            initUI(context, it)
            addToParent(parent, it)
        }
    }
}

fun Any.ui_ViewPager(id: String? = null, block: (UiViewPager.() -> Unit)? = null): UiViewPager
{
    val ui = UiViewPager(id)
    block?.let { ui.it() }
    if (this is UiGroup) addChild(ui)
    return ui
}

open class KtViewPager : ViewPager
{
    constructor(context: Context) : super(context)
    {
        initXML()
    }

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
    {
        initXML(context.obtainStyledAttributes(attrs, R.styleable.KtViewPager))
    }

    private fun initXML(typedArray: TypedArray? = null)
    {
        typedArray?.let()
        {
            if (it.hasValue(R.styleable.KtViewPager_kt_corner))
            {
                val corner = it.getDimensionOrThrow(R.styleable.KtViewPager_kt_corner).toInt()
                val cornerDirect = KtDirects[it.getInt(R.styleable.KtViewPager_kt_cornerDirect, 4)]

                outlineProvider = KtCornerProvider(corner, cornerDirect, this)
            }
            if (it.hasValue(R.styleable.KtViewPager_kt_isAlphaClick))
            {
                isAlphaClick = it.getBooleanOrThrow(R.styleable.KtViewPager_kt_isAlphaClick)
            }

            canMove = it.getBoolean(R.styleable.KtViewPager_kt_canMove, canMove)

            if (it.hasValue(R.styleable.KtViewPager_kt_pageLimit))
            {
                pageLimit = it.getIntOrThrow(R.styleable.KtViewPager_kt_pageLimit)
            }

            it.recycle()

            // 获取子view
            post()
            {
                if (adapter == null && childCount > 0)
                {
                    val list = children.toList()
                    removeAllViews()
                    setViewList(list)
                }
            }
        }
    }

    internal var pageLimit: Int? = null

    private fun resetLimit(size: Int)
    {
        pageLimit?.let { offscreenPageLimit = if (it >= size) size - 1 else it }
    }

    fun setViewList(viewList: List<View>)
    {
        resetLimit(viewList.size)
        viewAdapter.setNewList(viewList)
        adapter = viewAdapter
    }

    /** viewPager适配器 */
    val viewAdapter by lazy { KtViewPagerAdapter() }

    /******************************************** frag模式 **************************************/

    var fragmentManager: FragmentManager? = null
        internal set

    /** fragPager适配器 */
    val fragAdapter by lazy { KtFragPagerAdapter(fragmentManager!!) }

    fun setFragItems(list: List<KtFragItem>, fragmentManager: FragmentManager? = null)
    {
        resetLimit(list.size)
        this.fragmentManager = fragmentManager ?: (context as FragmentActivity).supportFragmentManager
        adapter = fragAdapter
        fragAdapter.setNewItems(list)
    }

    fun setFragItems(vararg items: KtFragItem)
    {
        setFragItems(items.toList(), null)
    }

    fun setFragments(list: List<Fragment>, fragmentManager: FragmentManager? = null)
    {
        resetLimit(list.size)
        this.fragmentManager = fragmentManager ?: (context as FragmentActivity).supportFragmentManager
        adapter = fragAdapter
        fragAdapter.setNewList(list)
    }

    fun setFragments(vararg frags: Fragment)
    {
        setFragments(frags.toList(), null)
    }

    fun getFragment(position: Int): Fragment?
    {
        val tag = "android:switcher:$id:$position"
        return fragmentManager?.findFragmentByTag(tag)
    }

    fun getNowFragment(): Fragment?
    {
        return getFragment(currentItem)
    }

    /********************************************** 其他 ****************************************/

    var canMove: Boolean = true

    override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean
    {
        return if (canMove)
        {
            super.onInterceptTouchEvent(ev)
        } else
        {
            false
        }
    }

    override fun onTouchEvent(ev: MotionEvent?): Boolean
    {
        return if (canMove)
        {
            super.onTouchEvent(ev)
        } else
        {
            false
        }
    }

    /********************************************** 点击 ****************************************/

    var isAlphaClick = false
        set(value)
        {
            field = value
            isClickable = value
        }

    override fun dispatchSetPressed(pressed: Boolean)
    {
        if (isAlphaClick) alpha = if (pressed || !isEnabled) 0.75f else 1f
        super.dispatchSetPressed(pressed)
    }

    override fun setEnabled(enabled: Boolean)
    {
        if (isAlphaClick) alpha = if (enabled) 1f else 0.75f
        super.setEnabled(enabled)
    }
}

/**
 * ViewPager适配
 */
class KtViewPagerAdapter(list: ArrayList<View> = ArrayList()) : PagerAdapter()
{
    /** viewPager列表 */
    val list: ArrayList<View> = list

    override fun getCount(): Int = list.size

    override fun isViewFromObject(view: View, o: Any): Boolean = view == o

    override fun destroyItem(container: ViewGroup, i: Int, o: Any)
    {
        container.removeView(o as View)
    }

    override fun instantiateItem(container: ViewGroup, i: Int): Any
    {
        val view = list[i]
        container.addView(view)
        return view
    }

    fun setNewList(list: List<View>)
    {
        this.list.clear()
        this.list.addAll(list)
        notifyDataSetChanged()
    }

    fun add(view: View)
    {
        list.add(view)
        notifyDataSetChanged()
    }

    fun remove(view: View)
    {
        list.remove(view)
        notifyDataSetChanged()
    }

    fun removeAt(i: Int)
    {
        list.removeAt(i)
        notifyDataSetChanged()
    }
}

/**
 * FragPager适配
 */
class KtFragPagerAdapter(val fragmentManager: FragmentManager, val list: ArrayList<Fragment> = ArrayList()) : FragmentPagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT)
{
    override fun getItem(position: Int): Fragment = list[position]

    override fun getCount(): Int = list.size

    fun setNewItems(items: List<KtFragItem>)
    {
        list.clear()
        list.addAll(items.map { it.fragment })
        notifyDataSetChanged()
    }

    fun setNewList(list: List<Fragment>)
    {
        this.list.clear()
        this.list.addAll(list)
        notifyDataSetChanged()
    }

    fun add(item: KtFragItem)
    {
        list.add(item.fragment)
        notifyDataSetChanged()
    }

    fun add(frag: Fragment)
    {
        list.add(frag)
        notifyDataSetChanged()
    }

    fun remove(frag: Fragment)
    {
        list.remove(frag)
        notifyDataSetChanged()
    }

    fun removeAt(i: Int)
    {
        list.removeAt(i)
        notifyDataSetChanged()
    }
}